import { Injectable, HttpException } from '@nestjs/common'
import * as nodemailer from 'nodemailer'
import { SendEmailCodeDto, SendPhoneCodeDto } from '../user/dto/verify-code.dto'
import emailConfig from '@/config/emailPush'
import regConfig from '@/config/reg.config'

interface VerificationCode {
  code: string
  expire: number
  type?: string
}

@Injectable()
export class VerificationService {
  private transporter: nodemailer.Transporter
  // 统一存储验证码：key为邮箱/手机号，value为验证码信息
  private verificationCodes = new Map<string, VerificationCode>()

  constructor() {
    this.initEmailTransporter()
    this.initExpiredCodeCleaner() // 初始化过期清理
  }

  // 初始化邮件 transporter（仅邮箱需要）
  private initEmailTransporter() {
    const isConfigComplete = Object.values(emailConfig).every(
      (value) => value !== undefined && value !== '',
    )
    if (!isConfigComplete) {
      throw new HttpException('邮件SMTP配置不完整', 400)
    }

    this.transporter = nodemailer.createTransport({
      host: emailConfig.host,
      port: emailConfig.port,
      secure: emailConfig.port === 465,
      auth: {
        user: emailConfig.user,
        pass: emailConfig.pass,
      }
    })

    this.transporter.verify((error) => {
      if (error) {
        console.error('邮件SMTP连接失败：', error.message)
        throw new HttpException(`邮件服务连接失败：${error.message}`, 503)
      }
      console.log('邮件SMTP连接已就绪')
    })
  }

  // 初始化、过期验证码清理
  private initExpiredCodeCleaner() {
    setInterval(() => {
      const now = Date.now()
      this.verificationCodes.forEach((value, key) => {
        if (value.expire < now) {
          this.verificationCodes.delete(key)
        }
      })
    }, 3600000) // 每小时清理一次
  }

  // 生成6位数字验证码
  private generateCode(): string {
    return Math.floor(100000 + Math.random() * 900000).toString()
  }

  // 存储验证码
  private storeCode(key: string, code: string, expireMinutes = 5, type?: string) {
    const expire = Date.now() + expireMinutes * 60 * 1000
    this.verificationCodes.set(key, { code, expire, type })
  }

  // 发送邮箱验证码
  async sendEmailCode(data: SendEmailCodeDto) {
    if (!regConfig.email.test(data.email)) {
      throw new HttpException('请输入正确的邮箱格式', 400)
    }
    try {
      const code = this.generateCode()
      this.storeCode(data.email, code, 5, 'email')

      const mailOptions: nodemailer.SendMailOptions = {
        from: `${emailConfig.fromName}<${emailConfig.user}>`,
        to: data.email,
        subject: '【味巷食谱】邮箱验证码',
        html: `<p style="font-size:24px; color:#333;">邮箱验证码</p>
              <p>尊敬的用户 ${data.email} 您好！</p>
              <p>您的验证码是：<span style="font-size:20px; color:#1890ff;font-weight:bold;">${code}</span></p>
              <p>请在 5 分钟内进行验证。如果该验证码不是您本人申请，请忽略。</p>`
      }

      await this.transporter.sendMail(mailOptions)
      return {
        success: true,
        message: '验证码已发送至您的邮箱'
      }
    } catch (error) {
      console.error('邮件发送失败：', error.message)
      throw new HttpException(`发送失败：${error.message || '未知错误'}`, 500)
    }
  }

  // 发送手机验证码
  async sendPhoneCode(data: SendPhoneCodeDto) {
    if (!regConfig.phone.test(data.phone)) {
      throw new HttpException('请输入正确的手机号', 400)
    }
    try {
      const code = this.generateCode()
      this.storeCode(data.phone, code, 5, 'phone')

      // 调用短信API
      const params = {
        targets: data.phone,
        code: code,
        number: 5
      }

      const response = await fetch('https://push.spug.cc/send/XlxGd8J4ndj2bn0R', {
        method: 'POST',
        body: JSON.stringify(params),
        headers: { 'Content-Type': 'application/json' }
      })

      const result = await response.json()

      if (result.code === 200 && result.msg === '请求成功') {
        return {
          success: true, message: '验证码已发送至您的手机'
        }
      } else {
        throw new HttpException(result.message || '短信发送失败', 500)
      }
    } catch (error) {
      console.error('短信发送失败：', error.message)
      throw new HttpException(`发送失败：${error.message || '未知错误'}`, 500)
    }
  }

  // 验证验证码
  verifyCode(key: string, code: string, type?: string): boolean {
    const codeInfo = this.verificationCodes.get(key)

    if (!codeInfo) {
      throw new HttpException('验证码不存在或已过期', 400)
    }

    if (codeInfo.expire < Date.now()) {
      this.verificationCodes.delete(key)
      throw new HttpException('验证码已过期，请重新获取', 400)
    }

    if (type && codeInfo.type !== type) {
      throw new HttpException('验证码用途不匹配', 400)
    }

    if (codeInfo.code !== code) {
      throw new HttpException('验证码错误', 400)
    }

    this.verificationCodes.delete(key) // 验证通过后删除，防止重复使用
    return true
  }
}